/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
package Tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * Implement function of Model of architecture MVC
 *
 * @author Ivan
 */
public class TModel {

    private static TModel instance;
    private String workDirectory;
    private Map<String, ACommand> mapCommands;
    private static IInitCommandFactory initCommandFactory;

    private TModel() {
        workDirectory = "C:\\";
        mapCommands = new HashMap<String, ACommand>(0);

    }

    public static TModel getInstance() throws Exception {
        if (instance == null) {
            instance = new TModel();
            FactorySingletonCommandConsole f = new FactorySingletonCommandConsole();
            f.initialisationMap();

        }
        return instance;

    }

    public IInitCommandFactory getInitCommandFactory() {
        return initCommandFactory;
    }

    public void setInitCommandFactory(IInitCommandFactory init) throws Exception {
        initCommandFactory = init;
        initCommandFactory.initialisationMap();
    }

    public String getWorkDirectory() {
        return workDirectory;
    }

    /*
    public List<String> parsingInputData(String inputOfUser) {
        List<String> parameters = new ArrayList<String>(0);
        String initializedParameter;

        String[] temp = inputOfUser.split("\\s");
        parameters.add(temp[0].toLowerCase(Locale.ENGLISH).intern());

        for (int i = 1; i < temp.length; i++) {
            initializedParameter = this.initialisationOfDirectory(temp[i].intern());
            parameters.add(initializedParameter);

        }
        return parameters;
    }
    * 
    */
    public List<String> parsingInputData(String inputOfUser) {
        List<String> parameters = new ArrayList<String>(0);
        String initializedParameter;

        String[] temp = inputOfUser.split("\\s",2);
        
        parameters.add(temp[0].toLowerCase(Locale.ENGLISH).intern());
        
        if(temp.length > 1){
           init(new Stack<String>(), temp[1].intern(),parameters); 
        }
        
        
        return parameters;
    }
    
    private void init(Stack<String> stack, String str, List<String> parameters) {
        String[] temp;
        File f;

        if (stack.size() != 0 || str.length() != 0) {
            str = initialisationOfDirectory(str);
            f = new File(str);
            if (!f.exists()) {
                temp = str.split("\\s");
                //if(temp.length > 1){
                   stack.push(temp[temp.length-1]);  
               // }
                
                str = "";
                for(int i = 0 ; i < temp.length-1; i++){
                   str+=temp[i] + " "; 
                }
                if(str != ""){
                    init(stack, str, parameters);  
                }else{
                    parameters.add(temp[0]);
                }
                         
               
            } else {
                parameters.add(str);
                str = "";
                while(!stack.isEmpty()){
                    str += stack.pop() + " ";
                }
                
                init(stack, str, parameters);
            }



        }
    }

    private String initialisationOfDirectory(String directory) {

        if (!directory.contains("*")) {
            Pattern pattern = Pattern.compile("([a-zA-Z]{1}:[\\a-zA-Zа-яА-Я\\d\\u002E\\u005F\\s]+)");
            Matcher matcher = pattern.matcher(directory);
            if (!matcher.matches()) {
                if (!workDirectory.endsWith("\\")) {
                    workDirectory += "\\";
                }

                directory = workDirectory + directory;

            }
        }
        try {

            File temp = new File(directory);
            if (temp.exists()) {
                directory = temp.getCanonicalPath();
            }

        } catch (Exception e) {
        }

        return directory;
    }

    private class TMkDir extends ACommand {

        private final static String commandName = "mkdir";
        private String messageAboutError = "";

        private TMkDir(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);
        }

        @Override
        public Object action(String key) throws IOException {
            File file;
            for (String directory : validParameters) {
                file = new File(directory);
                file.mkdir();
            }
            return true;
        }

        @Override
        public void setParameters(List<String> parameters) throws IOException {

            if ((parameters == null) || (parameters.size() < 1)) {
                throw new IOException("Error in syntax of command!");
            }
            File f;

            for (String directory : parameters) {
                f = new File(directory);
                if (f.exists()) {
                    messageAboutError += "Subfolder or file " + f.getName() + " already exist!\n";
                } else {
                    validParameters.add(directory);
                }
            }
            if (messageAboutError.length() != 0) {
                throw new IOException(messageAboutError);
            }
        }

        @Override
        public void isValidKey(String key) throws Exception {
        }
    }

    private class TCopy extends ACommand {

        private final static String commandName = "copy";
        private BufferedReader reader;
        private BufferedWriter writer;
        private String destinationDirectory;
        private List<String> processedFiles = new ArrayList<String>(0);

        public TCopy() {
            super(commandName);
            stringPrintResult = new StringBuffer();
        }

        public TCopy(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);
            stringPrintResult = new StringBuffer();

        }

        @Override
        public synchronized Object action(String key) throws IOException, InterruptedException {
            File fileSource, fileDestination;

            for (String pathname : validParameters) {
                if (!processedFiles.contains(pathname)) {

                    fileSource = new File(pathname);
                    fileDestination = new File(destinationDirectory);

                    reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileSource)));

                    if (fileDestination.isDirectory()) {
                        fileDestination = new File(destinationDirectory + "\\" + fileSource.getName());
                    }

                    if ((fileDestination.exists()) && (!"all".equals(key))) {

                        if (key == null) {

                            setPrintResult(stringPrintResult);


                            extraThread.initializeExtraThread(this, "Replace " + fileDestination.getName() + " [Yes(да) \\ No(нет) \\ All(все)]: ", key);
                            extraThread.getThread().start();

                            wait();

                            return false;

                        } else if (key == "yes") {
                            if ((extraThread != null) && (extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                                extraThread.getThread().interrupt();
                                notify();

                            }

                            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileDestination)));
                            key = null;
                        } else if (key == "no") {
                            if ((extraThread != null) && (extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                                extraThread.getThread().interrupt();
                                notify();
                            }
                            continue;
                        }
                    } else {
                        if ((extraThread != null) && (extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                            extraThread.getThread().interrupt();
                            notify();
                        }
                        writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileDestination)));
                    }

                    if ((extraThread != null) && (extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                        extraThread.getThread().interrupt();
                        notify();
                    }

                    while (reader.ready()) {
                        writer.write(reader.readLine());
                    }

                    reader.close();
                    writer.close();
                    processedFiles.add(pathname);
                }
            }

            stringPrintResult.append("Amount of the copied files : " + processedFiles.size() + "\n");
            setPrintResult(stringPrintResult);
            processedFiles = new ArrayList<String>(0);
            return true;
        }

        public void setParameters(List<String> parameters) throws IOException {

            File file;
            if ((parameters == null) || (parameters.size() == 0) || (parameters.size() > 2)) {
                throw new IOException("Error of syntaxis of command!\n");
            }

            if (parameters.size() == 1) {
                destinationDirectory = workDirectory;
            } else {
                file = new File(parameters.get(1));
                destinationDirectory = parameters.get(1);
            }

            file = new File(parameters.get(0));
            if (!file.exists()) {
                throw new IOException("didn't could find specief file!\n");
            } else {
                if (file.isDirectory()) {
                    for (File externFile : file.listFiles()) {
                        if (externFile.isFile()) {
                            validParameters.add(externFile.getAbsolutePath());
                        }
                    }
                } else {
                    validParameters.add(parameters.get(0));
                }
            }

        }

        @Override
        public void isValidKey(String key) throws Exception {
            if ((key == null) || (key == "yes") || (key == "no") || (key == "all")) {
            } else {
                if ((extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                    extraThread.getThread().interrupt();
                    throw new Exception("key is invalid!\n");
                }
            }
        }
    }

    private class TMove extends ACommand {

        private final static String commandName = "move";

        public TMove(IExtraThreadFactory extraThread) {
            super("commandName", extraThread);
            extraThread = new CommandExtraThreadIOStream();
        }

        @Override
        public synchronized Object action(String key) throws Exception {
            boolean result = true;
            TCopy copy = new TCopy();
            TDel del = new TDel();


            copy.setParameters(validParameters);
            copy.action("all");

            del.setParameters(copy.validParameters);
            del.action("yes");
            setPrintResult(new StringBuffer("moved complete\n"));

            return result;
        }

        @Override
        public void setParameters(List<String> parameters) throws IOException {

            File fileSource;
            File fileDestination;

            if ((parameters.size() == 0) || (parameters.size() > 2)) {
                throw new IOException("Error in syntax of command!");
            } else {
                if (parameters.size() == 1) {
                    fileDestination = new File(workDirectory);
                } else {
                    fileDestination = new File(parameters.get(1));
                }
                fileSource = new File(parameters.get(0));

                if (!fileSource.exists()) {
                    throw new IOException("didn't could find source file!\n");
                } else {
                    if (!fileSource.isDirectory()) {
                        if (fileDestination.isDirectory()) {
                            for (File externFile : fileDestination.listFiles()) {
                                if (externFile.getName() == fileSource.getName()) {
                                    throw new IOException("File is exist\n");
                                }
                            }
                        } else if (fileDestination.getName() == fileSource.getName()) {
                            throw new IOException("File is exist\n");
                        }
                    } else {
                        throw new IOException("access is denied\n");
                    }
                }
            }
            validParameters = parameters;
        }

        @Override
        public void isValidKey(String key) throws Exception {
        }
    }

    private class TDel extends ACommand {

        private final static String commandName = "del";
        private List<String> processedFiles;
        private List<String> deletedFiles;

        private TDel(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);
            processedFiles = new ArrayList<String>(0);
            deletedFiles = new ArrayList<String>(0);
        }

        private TDel() {
            super(commandName);
            processedFiles = new ArrayList<String>(0);
            deletedFiles = new ArrayList<String>(0);
        }

        @Override
        public synchronized Object action(String key) throws Exception {
            File file;
            boolean isDeleted;

            for (String puthName : validParameters) {
                if (!processedFiles.contains(puthName) && (key != "no")) {

                    file = new File(puthName);
                    if (!file.exists()) {
                        stringPrintResult.append("didn't could find file " + file.getAbsolutePath() + "!\n");
                        setPrintResult(stringPrintResult);
                    } else {
                        if (file.isDirectory()) {
                            if (key == "yes") {
                                if ((extraThread != null) && (extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                                    extraThread.getThread().interrupt();
                                    notify();
                                }
                                for (File subfile : file.listFiles()) {
                                    isDeleted = subfile.delete();
                                    if (!isDeleted) {
                                        stringPrintResult.append("file : " + subfile.getAbsolutePath() + "didn't was deleted\n");
                                    } else {
                                        deletedFiles.add(subfile.getAbsolutePath());
                                    }
                                }
                                key = null;
                                processedFiles.add(puthName);

                            } else {

                                //if (!extraThread.getThread().isAlive()) {
                                //   extraThread = new CommandThreadIOStream().t;
                                // }
                                extraThread.initializeExtraThread(this, file.getAbsolutePath() + "\\*  , Continue [Yes(да) \\ No(нет)] ?  ", key);
                                extraThread.getThread().start();
                                wait();
                                return false;
                            }

                        } else {
                            isDeleted = file.delete();
                            if (!isDeleted) {
                                stringPrintResult.append("file : " + file.getAbsolutePath() + " didn't was deleted\n");
                            } else {
                                deletedFiles.add(file.getAbsolutePath());

                            }
                            key = null;
                            processedFiles.add(puthName);
                        }
                    }
                } else if ((key == "no") && !processedFiles.contains(puthName)) {
                    key = null;

                    processedFiles.add(puthName);
                    if ((extraThread != null) && (extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                        extraThread.getThread().interrupt();
                        notify();

                    }
                }

            }

            stringPrintResult.append("Deleted : " + deletedFiles.size() + " files\n");
            processedFiles.clear();
            deletedFiles.clear();
            setPrintResult(stringPrintResult);
            return true;
        }

        @Override
        public void setParameters(List<String> parameters) throws IOException {
            if (parameters.size() == 0) {
                throw new IOException("Error of syntaxis of command!\n");
            } else {
                validParameters = parameters;
            }
        }

        @Override
        public void isValidKey(String key) throws Exception {
            if ((key == null) || (key == "yes") || (key == "no")) {
            } else {
                if ((extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                    extraThread.getThread().interrupt();
                    throw new Exception("key is invalid!\n");
                }
            }
        }
    }

    private class TDir extends ACommand {

        private final static String commandName = "dir";
        private Map<String,String> map =  new HashMap<String, String>(0);;

        private TDir() {
            super(commandName);
        }

        private TDir(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);
        }

        public void browseDirectory(File directoty, StringBuffer stringPrintResult) {
            map.clear();
            if (directoty.isDirectory()) {
                for (File subFile : directoty.listFiles()) {
                    if (subFile.isDirectory()) {
                        stringPrintResult.append(subFile.getName() + "\t <DIR> \t" + new Date(subFile.lastModified()).toString() + "\n");
                        
                        map.put(subFile.getName(), "\t <DIR> \t" + new Date(subFile.lastModified()).toString());
                    } else {
                        stringPrintResult.append(subFile.getName() + "\t <File>\t" + new Date(subFile.lastModified()).toString() + "\n");
                        
                         map.put(subFile.getName(), "\t <File>\t" + new Date(subFile.lastModified()).toString());
                    }
                }
            } else {
                stringPrintResult.append(directoty.getName() + "\t <File>\t" + new Date(directoty.lastModified()).toString() + "\n");
                 map.put(directoty.getName(), "\t <File>\t" + new Date(directoty.lastModified()).toString());
            }
        }

        /**
         * This method displays the content of the directory which specified as parameter.
         * @param parameters
         * @return
         * @throws Exception
         */
        @Override
        public Object action(String key) throws IOException {
            File root;
            map.clear();

            for (String puthName : validParameters) {
                //Initialization of root directory
                root = new File(puthName);

                if (root.isDirectory()) {
                   // stringPrintResult.append("Contens of folder  ").append(puthName).append(" :\n");

                    //Print result
                    browseDirectory(root, stringPrintResult);

                    stringPrintResult.append("\n");
                }
            }
            return map;
        }

        @Override
        public void setParameters(List<String> parameters) throws IOException {
            File file;
            validParameters.clear();
            
            if (parameters.size() == 0) {
                validParameters.add(workDirectory);
            } else {
                for (String puthName : parameters) {
                    file = new File(puthName);
                    if (file.exists()) {
                        if (file.isDirectory()) {
                            validParameters.add(puthName);
                        } else {
                            stringPrintResult.append("File ").append(puthName).append(" is not folder!\n");
                        }

                    } else {
                        stringPrintResult.append("File ").append(puthName).append(" is no found!\n");
                    }
                }
            }

        }

        @Override
        public void isValidKey(String key) throws Exception {
        }
    }

    private class TCDir extends ACommand {

        private final static String commandName = "cd";

        private TCDir(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);

        }

        private TCDir() {
            super(commandName);

        }

        @Override
        public Object action(String key) throws IOException {

            File temp = new File(validParameters.get(0));

            if (!temp.isDirectory()) {
                throw new IOException("Directory  \"" + validParameters.get(0) + "\" is not exist!\n");
            } else {

                workDirectory = validParameters.get(0);
            }

            setPrintResult(new StringBuffer("work directory was changed\n"));
            return true;
        }

        @Override
        public void setParameters(List<String> parameters) throws IOException {

            File file;
            IOException e = new IOException("system can not find specief path \n");
            if ((parameters.size() > 1) || (parameters.isEmpty())) {
                throw e;
            } else {
                file = new File(parameters.get(0).intern());
                if (!file.exists()) {
                    throw e;
                }

                if (parameters.get(0).endsWith("/")) {
                }
            }

            validParameters = parameters;
        }

        @Override
        public void isValidKey(String key) throws Exception {
        }
    }

    private class TTree extends ACommand {

        private final static String commandName = "tree";
        private LinkedHashMap<String,String> map;
        private TTree(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);
        }

        private TTree() {
            super(commandName);
        }

        //Recursive method search in depth with display of tree
        private void depthSearchPrint(File root, String strTab) throws IOException{
            
            String strClildNode = strTab + "└────";
            String fileName = null;

            if (!root.isHidden() && root.listFiles() != null) {
                for (File file : root.listFiles()) {

                    fileName = file.getName();

                    stringPrintResult.append(strClildNode + fileName + "\n");
                    map.put(file.getCanonicalPath(),strClildNode + fileName+ "\n");
                    if ((file.listFiles() != null) && (file.listFiles().length != 0)) {
                        //strTab += "\t";
                        strTab += "     ";
                        depthSearchPrint(file, strTab);
                    }
                }
            }

        }

        /**
         * This method  displays the directory tree and theirs content in console window.
         * Name of initial directory transfered as input parameter.
         * @param parameters
         * @return
         * @throws Exception
         */
        @Override
        public Object action(String key) throws IOException {
            map = new LinkedHashMap<String, String>(0);//Map<String, String>(0);
            
            //Initialization of root directory
            File root = new File(validParameters.get(0));

            //List of all files which were found in specified directory
            List<File> nodes = new ArrayList<File>(0);
            nodes = Arrays.asList(root.listFiles());

            String tree = null;
            ///Display of tree
            for (File file : nodes) {
                tree = "├────" + file.getName() + "\n";
                //System.out.print(tree);
                stringPrintResult.append(tree);
                map.put(file.getCanonicalPath(), tree);
                

                if (file.isDirectory()) {
                    depthSearchPrint(file, "|     ");
                }
            }
            setPrintResult(stringPrintResult);
            return map;
        }

        @Override
        public void setParameters(List<String> parameters) throws IOException {

            if (parameters.size() > 1) {
                throw new IOException("So many parameters!");
            } else if (parameters.size() == 0) {
                parameters.add(workDirectory);
            }

            File file = new File(parameters.get(0));

            if (file.exists() && file.isDirectory()) {
                validParameters = parameters;
            } else {
                throw new IOException("Path specief incorrect : " + parameters.get(0) + "\nSubfolders is not exist!");
            }
        }

        @Override
        public void isValidKey(String key) throws Exception {
        }
    }

    private class TSearcher extends ACommand {

        private LinkedHashMap<String,String> map;
        private final static String commandName = "find";
        private TMaskCaseSensitive filter;
        //  private StringBuffer stringPrintResult;
        private String direcotyOfSearch;

        private TSearcher(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);

            stringPrintResult = new StringBuffer();
        }

        private TSearcher() {
            super(commandName);

            stringPrintResult = new StringBuffer();
        }

        //Recursive method search in depth
        private void depthSearch(File root, ArrayList<File> AllFiles) {
            for (File node : root.listFiles()) {
                AllFiles.add(node);
                if ((node.listFiles() != null) && (node.listFiles().length != 0)) {
                    depthSearch(node, AllFiles);
                }
            }
        }

        /**
         *This method displays the content of the directory with extended information using searching mask.
         *Directory and mask of search specified as parameters this methods.
         * @param parameters
         * @return
         * @throws Exception
         */
        @Override
        public Object action(String key) throws IOException {
            map = new LinkedHashMap<String, String>(0);
            TDir dir = new TDir();
            //Initialization of root directory
            File root = new File(direcotyOfSearch);

            //List of all files which were found in specified directory
            ArrayList<File> all_found_files = new ArrayList<File>(0);

            //List of files which satisfy requirement mask of searching
            ArrayList<File> processed_files = new ArrayList<File>(0);

            //Search all files
            depthSearch(root, all_found_files);

            // Verification on compliance
            for (File file : all_found_files) {
                if (filter.match(file)) {
                    processed_files.add(file);
                    map.put(file.getAbsolutePath(), file.getName());
                }
            }

            //Print result
            System.out.print("(Amount of found files : " + processed_files.size() + ") \n");
            for (File file : processed_files) {
                dir.browseDirectory(file, stringPrintResult);

            }

            setPrintResult(stringPrintResult);
            return map;
        }

        @Override
        public void setParameters(List<String> parameters) throws Exception {
            if ((parameters.size() == 0) || (parameters.size()) > 2) {
                throw new IOException("Mack specified incorrect!\n");
            } else {
                filter = new TMaskCaseSensitive(parameters.get(0));
                if (parameters.size() == 1) {
                    direcotyOfSearch = workDirectory;
                } else {
                    direcotyOfSearch = parameters.get(1);
                }
            }
        }

        @Override
        public void isValidKey(String key) throws Exception {
        }
    }

    private class TCloser extends ACommand {

        private final static String commandName = "exit";

        private TCloser(IExtraThreadFactory extraThread) {
            super(commandName, extraThread);

        }

        private TCloser() {
            super(commandName);
        }

        @Override
        public synchronized Object action(String key) throws Exception {
            if (((key == null) || (key != "yes")) && (key != "no")) {

                if ((extraThread.getThread() == null) || (!extraThread.getThread().isAlive())) {
                    extraThread.initializeExtraThread(this, "Are you sure? [Yes / No] : ", key);
                }

                extraThread.getThread().start();
                wait();
                return false;
            } else if (key == "yes") {
                if (((extraThread.getThread() != null) && (extraThread.getThread().isAlive()))) {
                    extraThread.getThread().interrupt();
                    notify();
                }

                System.exit(0);

            } else {
                if ((extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                    extraThread.getThread().interrupt();
                    notify();
                }
            }
            return true;
        }

        @Override
        public void setParameters(List<String> parameters) throws Exception {
            if (parameters.size() > 0) {
                throw new IOException("this command can't contains parameters!");
            }
        }

        @Override
        public synchronized void isValidKey(String key) throws Exception {
            if ((key == null) || ("yes".equals(key)) || ("no".equals(key))) {
            } else {
                if ((extraThread.getThread() != null) && (extraThread.getThread().isAlive())) {
                    extraThread.getThread().interrupt();
                    throw new Exception("key is invalid!\n");
                }
            }

        }
    }

    /**
     * This class implements initialization of  mask of searching.
     * @author Ivan
     *
     */
    public class TMaskCaseSensitive {

        private final String FILTER_MASK = "((\\*){1}[a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+(\\*)?)|((\\*){1}[a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+(\\*){1})|((\\*)?[a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+(\\*){1})";
        private String filter;
        private Pattern pattern;
        private Matcher matcher;
        private String mask;

        public TMaskCaseSensitive(String mask) throws PatternSyntaxException, InitializationMaskException {
            this.mask = mask;

            //initialization of pattern
            pattern = Pattern.compile(FILTER_MASK);
            matcher = pattern.matcher(mask);

            //validation of the entered search mask
            if (!matcher.matches()) {
                throw new InitializationMaskException("mask entered incorrect!");
            }
        }

        public boolean match(File f) {

            String targetStr = "";
            for (Character ch : mask.toCharArray()) {
                if (ch != '*') {
                    targetStr += ch;
                }
            }

            if (mask.startsWith("*") && mask.endsWith("*")) {
                filter = "([a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+)?(" + targetStr + ")([a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+)?";
            } else if (mask.startsWith("*")) {
                filter = "[a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+(" + targetStr + ")";
            } else if (mask.endsWith("*")) {
                filter = "(" + targetStr + ")[a-zA-Zа-яА-Я\\d\\s\\u005F\\u002E]+";
            }

            //initialization of pattern
            pattern = Pattern.compile(filter);
            matcher = pattern.matcher(f.getName());

            //check the file name in accordance with the search mask
            if (matcher.matches()) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * Class of exception, which called in case incorrect enter value of mask of search.
         * @author Ivan
         */
        public class InitializationMaskException extends Exception {

            private static final long serialVersionUID = 1L;

            public InitializationMaskException(String message) {
                super(message);
            }
        }
    }
}
